package com.system.questionnairesurvey.common.log.aspect;

import com.google.gson.Gson;
import com.system.questionnairesurvey.common.log.annotation.SysLog;
import com.system.questionnairesurvey.common.util.ip.HttpContextUtils;
import com.system.questionnairesurvey.common.util.ip.IPUtils;
import com.system.questionnairesurvey.entity.mybatis.SysLogEntity;
import com.system.questionnairesurvey.service.SysLogService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Date 2022/3/1 13:32
 * @Created by wlh
 */
@Slf4j
@Aspect
@Component
@AllArgsConstructor
public class SysLogAspect {

    private final SysLogService logService;

    @Pointcut("@annotation(com.system.questionnairesurvey.common.log.annotation.SysLog)")
    public void logPoint() {
    }

    /**
     * 环绕增强
     */
    @Around(value = "logPoint()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        // 执行方法
        Object result = point.proceed();
        // 执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        // 保存日志信息
        saveSysLog(point, time, result);
        return result;
    }

    private void saveSysLog(ProceedingJoinPoint point, long time, Object result) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();

        SysLogEntity entity = new SysLogEntity();
        SysLog syslog = method.getAnnotation(SysLog.class);
        if (syslog != null) {
            // 注解描述
            entity.setOperation(syslog.value());
        }

        // 请求的方法名
        String className = point.getTarget().getClass().getName();
        String methodName = signature.getName();
        entity.setMethod(className + "." + methodName + "()");

        // 请求的参数
        Object[] args = point.getArgs();
        List<Object> list = new ArrayList<>();
        try {
            for (Object arg : args) {
                if (!(arg instanceof HttpServletRequest)) {
                    list.add(arg);
                }
            }
            String params = new Gson().toJson(list);
            entity.setParams(params);
            String res = new Gson().toJson(result);
            entity.setRes(res);
        } catch (Exception e) {
            log.error("获取请求参数异常:{}", e.getMessage());
        }

        //获取request
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        //设置IP地址
        entity.setIp(IPUtils.getIpAddr(request));

        entity.setTime((int) time);
        entity.setCreateTime(new Date());
        // 待处理用户编码 TODO
        entity.setUserCode(null);
        logService.save(entity);
    }


}
